/*
* Copyright (C) 2009-2012 - Roman Kalynchuk
*
* This file is part of REngine.
*
* REngine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* REngine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with REngine.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __IRENDERDRIVER_SDL_H__
#define __IRENDERDRIVER_SDL_H__

#include "mathlib/vec2.h"
#include "mathlib/vec3.h"
#include "mathlib/mat4.h"
#include "render/irenderdriver.h"
#include "render/ivertexbuffer.h"
#include "render/imesh.h"
#include "SDL/SDL.h"
#include <windows.h>

namespace rengine3d {

	const int maxClipPlanes = 6;

	class IVarSystem;
	class IFileSystem;

	class CRenderDriverSDL: public IRenderDriver {
	public:
		CRenderDriverSDL(IVarSystem* varSys, IFileSystem* fileSys);
		virtual ~CRenderDriverSDL();

		virtual bool Init(void);
		virtual void Shutdown(void);

		virtual string_t GetName(void);
		virtual string_t GetDescription(void);
		virtual string_t GetVersion(void);

		virtual void SetDisplayMode(uint w, uint h, bool fs);

		virtual void SetViewport(int x, int y, unsigned int width, unsigned int height);

		virtual void ShowCursor(bool value);

		virtual void SetVSync(bool enabled);
		virtual bool GetVSync(void);

		virtual void SetIdentity(matrixType_t matrixType);
		virtual void SetMatrix(matrixType_t matrixType, const CMat4& mat);
		virtual const CMat4& GetMatrix(matrixType_t matrixType);
		virtual void PushMatrix(matrixType_t matrixType);
		virtual void PopMatrix(matrixType_t matrixType);
		virtual void Translate(matrixType_t matrixType, const CVec3& pos);
		virtual void Rotate(matrixType_t matrixType, const CVec3& rot);
		virtual void Scale(matrixType_t matrixType, const CVec3& scale);
		virtual void Ortho(real r, real b, real zNear, real zFar);

		virtual void SetColor(const CVec4& color);

		virtual void Clear(void);

		virtual void SetTexture(unsigned int unit, ITexture* tex);
		virtual void SetRenderTarget(ITexture* tex);
		//virtual uint UploadTexture(void* data, uint width, uint height, bool mipMaps, int mipLevel, int cubeSide, textureType_t type, textureFormat_t format, textureFilter_t filter );
		virtual void UnloadTexture( uint id, textureTarget_t target );

		virtual void SwapBuffers(void);
		virtual void Flush(void);

		virtual void SetClipPlane(int ind, const CPlane& plane);
		virtual CPlane GetClipPlane(int ind);

		virtual void SetTextureEnv(textureParam_t param, int value);
		virtual void SetTextureConstantColor(const CVec4& color);

		virtual void SetClearColor(const CVec4& color);
		virtual void SetClearDepth(float value);
		virtual void SetClearStencil(int value);
		virtual void SetClearColorActive(bool active);
		virtual void SetClearDepthActive(bool active);
		virtual void SetClearStencilActive(bool active);
		virtual void SetColorWriteActive(bool activeR, bool activeG, bool activeB, bool activeA);
		virtual void SetDepthWriteActive(bool active);
		virtual void SetDepthTestActive(bool active);
		virtual void SetDepthTestFunc(depthTestFunc_t func);
		virtual void SetAlphaTestActive(bool active);
		virtual void SetAlphaTestFunc(alphaTestFunc_t func, float ref);
		virtual void SetStencilActive(bool active);
		virtual void SetStencilTwoSideActive(bool active);
		virtual void SetStencilFace(stencilFace_t face);
		virtual void SetStencilFunc(stencilFunc_t func,int ref, unsigned int mask);
		virtual void SetStencilOp(stencilOp_t failOp, stencilOp_t zFailOp, stencilOp_t zPassOp);
		virtual void SetStencil(stencilFunc_t func, int ref, unsigned int mask, stencilOp_t failOp, stencilOp_t zFailOp, stencilOp_t zPassOp);
		virtual void SetStencilTwoSide(stencilFunc_t frontFunc, stencilFunc_t backFunc, int ref, unsigned int mask,
						stencilOp_t frontFailOp, stencilOp_t frontZFailOp, stencilOp_t frontZPassOp,
						stencilOp_t backFailOp,  stencilOp_t backZFailOp,  stencilOp_t backZPassOp);

		virtual void SetCullActive(bool active);
		virtual void SetCullMode(cullMode_t mode);
		virtual void SetScissorActive(bool active);
		virtual void SetScissorRect(int x, int y, int w, int h);

		virtual void SetBlendActive(bool active);
		virtual void SetBlendFunc(blendFunc_t srcFactor, blendFunc_t destFactor);

		virtual void SetMultisamplingActive(bool enable);

		virtual void SetGamma(float gamma);
		virtual float GetGamma(void);

		virtual void EnableFog(void);
		virtual void DisableFog(void);

		virtual void EnableTexture(void);
		virtual void DisableTexture(void);

		virtual void DrawRect(const CVec2& pos,const CVec2& size, float z);
		virtual void DrawTris(const vertexVector_t& vertex);
		virtual void DrawTris(CDrawVertex* vertex);
		virtual void DrawQuad(const vertexVector_t& vertex);
		virtual void DrawLine(const CVec3& begin, const CVec3& end, CVec4 color);
		virtual void DrawBoundBox(const CBoundBox& bbox, CVec4 color);
		virtual void DrawLine2D(const CVec2& begin, const CVec2& end, float z, CVec4 color);

		virtual CVec2 GetScreenSize(void);
		virtual CVec2 GetVirtualSize(void) { return m_virtualSize; } ;

		virtual int GetCaps(renderCaps_t type);

		virtual IVertexBuffer* CreateVertexBuffer(uint flags, vbDrawType_t drawType, vbUsageType_t usageType);

		virtual void BindTexture(uint textureId, uint multiTextureId);

		virtual ITexture* CreateTexture(bool useMipMaps, textureType_t type, textureTarget_t target);
		virtual ITexture* CreateTexture(const string_t& name, bool useMipMaps, textureType_t type, textureTarget_t target);

		virtual void ForTest(void);

		//virtual const string_t& GetName(void) const { return m_name;};
	private:
		bool InitGL(void);
		void ShutdownGL(void);
		
		void SetToGLMatrixMode(matrixType_t matrixType);
//		uint CalcTextureSize(textureFormat_t format, int width, int height);
	private:
		//string_t	m_name;
		//bool		m_initialized;
		bool		m_isBeginFrame;
		void*		m_windowHandle;
		
		CVec2		m_screenSize;
		CVec2		m_virtualSize;

		bool		m_vSync;
		bool		m_isExternal;
		bool		m_fullScreen;
		uint		m_multiSampling;
		uint		m_width;
		uint		m_height;
		int			m_colourDepth;

		bool		m_clearDepth;
		bool		m_clearColor;
		bool		m_clearStencil;

		CMat4		m_proj;
		CMat4		m_modelView;
		CMat4		m_invModelView;

		string_t	m_vendor;
		string_t	m_renderer;
		string_t	m_version;
		string_t	m_extensions;

		float		m_gamma;

		SDL_Surface*		m_screen;


#if PLATFORM == PLATFORM_WIN32
		HDC						m_hDC;
		HGLRC					m_hGLRC;
#endif
		int						m_curVideoMode;

		IVarSystem*				m_varSys;
		IFileSystem*			m_fileSys;

		CPlane m_clipPlanes[maxClipPlanes];
	};

}

#endif
